#ifndef C_DX_MESH_H_
#define C_DX_MESH_H_

// The include files for Direct3D9
#include <d3d9.h>
#include <d3dx9.h>

#include <vector>

#include "Math.h"
#include "CDXMeshComponent.h"

#define DXMESH_BAD_MESH_ID	UINT_MAX

class CDXMeshManager;

// Base Interface class for Meshes
class IDXMesh
{
protected:
	enum MeshType
	{
		MESHTYPE_NULL = 0,
		MESHTYPE_DX,
		MESHTYPE_USER_DEFINED
	};
	UINT		m_ref;
	UINT		m_meshType;
	UINT		m_ID;

	char		m_meshName[16];

	// Is the mesh a DX Primitive object?
	bool		m_isPrimitive;

public:

	friend class CDXMeshManager;

	IDXMesh(UINT meshType = MESHTYPE_NULL);
	IDXMesh(const IDXMesh&);
	IDXMesh& operator=(const IDXMesh&);
	~IDXMesh();

	virtual void DrawMesh(IDirect3DDevice9* pDXDevice) = 0;
	virtual void DeleteMesh();

	//Accessors
	UINT GetMeshID()	{	return m_ID;		}
	char* GetMeshName()	{	return m_meshName;	}
	UINT GetType()		{	return m_meshType;	}
protected:
	void SetMeshID(UINT ID)					{	m_ID = ID;	}
	void SetMeshName(char* meshName)		{	strcpy_s(m_meshName, 16, meshName);	}
	void SetIsPrimitive(bool IsPrimitive)	{	m_isPrimitive = IsPrimitive;	}
};

// DirectX meshes loaded in from ".x" files
class CDXDirectXMesh : public IDXMesh
{
private:
	ID3DXMesh*	m_mesh;
	std::vector<int>	m_textures;
	std::vector<D3DMATERIAL9> m_materials;
	
public:

	friend class CDXMeshManager;

	CDXDirectXMesh();
	CDXDirectXMesh(const CDXDirectXMesh&);
	CDXDirectXMesh& operator=(const CDXDirectXMesh&);
	~CDXDirectXMesh();

	void DrawMesh(IDirect3DDevice9* pDXDevice);
	void DeleteMesh();

	bool LoadMesh(const char* FileName, IDirect3DDevice9* pDXDevice);
	bool UnloadMesh();
};

// User-defined meshes which can be used to load and create your own meshes
class CDXUserMesh : public IDXMesh
{
public:
	vec3f*	m_vertices;
	vec3f*	m_normals;
	vec3f*	m_texCoords;

	unsigned m_numVerts;
	unsigned m_numTriangles;

	CDXMeshComponent::Triangle*	m_triangles;
	std::vector<int>	m_textures;

	LPDIRECT3DVERTEXBUFFER9 m_vertexBuffer;
	LPDIRECT3DINDEXBUFFER9	m_indexBuffer;

	//Function Pointers for drawing and deleting mesh
	typedef void (*DXMeshDrawPtr)(IDirect3DDevice9*);
	typedef void (*DXMeshDelPtr)(void);
	DXMeshDrawPtr f_DrawFunc;
	DXMeshDelPtr f_DeleteFunc;


	friend class CDXMeshManager;

	CDXUserMesh();
	CDXUserMesh(DXMeshDrawPtr drawFuncPtr, DXMeshDelPtr deleteFuncPtr);
	CDXUserMesh(const CDXUserMesh&);
	CDXUserMesh& operator=(const CDXUserMesh&);
	~CDXUserMesh();

	void DrawMesh(IDirect3DDevice9* pDXDevice);
	void DeleteMesh();

};

#endif